package com.sf.shiva.oms.common.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sf.shiva.oms.common.constant.CommonConstant;
import com.sf.shiva.oms.common.exception.OmsException;
import com.sf.shiva.oms.common.exception.OmsRuntimeException;
import com.sf.shiva.oms.common.extend.utils.DateTimeFormatUtils;
import com.sf.shiva.oms.common.extend.utils.DateTimeUtils;


/**
 * 描述：日期工具类，主要是对日期进行 格式上面的处理，日期的加减以及 判断日期是否符合标准格式
 * 
 * <pre>
 * HISTORY
 * ****************************************************************************
 *  ID   DATE           PERSON          REASON
 *  1    2016年3月10日            879149          Create
 * ****************************************************************************
 * </pre>
 * 
 * @author 879149
 * @since 1.0
 */
public class DateUtil {

    private DateUtil(){}
    public static final String MONDAY = "1";// 星期一
    public static final String TUESDAY = "2"; // 星期二
    public static final String WEDNESDAY = "3"; // 星期三
    public static final String THURSDAY = "4";// 星期四
    public static final String FRIDAY = "5";// 星期五
    public static final String SATURDAY = "6";// 星期六
    public static final String SUNDAY = "7";// 星期日
    
    private static final String DATE_TIME="yyyy-MM-dd HH:mm:ss";//日期+时间
    private static final String DATE_MINUTE="yyyy-MM-dd HH:mm";//日期+时间(无秒钟)
    private static final String DATE="yyyy-MM-dd";//日期
    private static final String DATE_TIME_NUMBER_MM="yyyyMMddHHmm";//日期+时间(纯数字到分钟)
    
    private static final String DATE_TIME_FOR_ORDER_NO = "MMddHHmmssSSS"; //订单号生成规则时间格式
    
    private static final Logger logger = LoggerFactory.getLogger(DateUtil.class);
    /**
     * 是否为周末
     * 
     * @param date
     *            时间
     * @return true/false
     * @author zhangYao 568677
     * @date 2015年6月10日
     */
    public static boolean isWeekend(Date date) {
        String workday = DateTimeUtils.getWorkday(date);
        return StringUtils.equals(SATURDAY, workday)
                || StringUtils.equals(SUNDAY, workday);
    }

    /**
     * 获取间隔分钟数，不取绝对值 secondDate - firstDate
     * 
     * @param firstDate
     *            第一个时间
     * @param secondDate
     *            第二个时间
     * @return 间隔分钟数
     * @author zhangYao 568677
     * @date 2015年7月7日
     */
    public static int getDistanceMMForNoAbs(Date firstDate, Date secondDate) {
        long firstMs = firstDate.getTime();
        long secondMs = secondDate.getTime();
        return (int) ((secondMs - firstMs) / 60000L);
    }

    /**
     * 将字符串日期转换为Date
     * 
     * @param dateStr
     *            时间字符串，格式为：yyyy-MM-dd HH:mm:ss
     * @return date
     * @author zhangYao 568677
     * @date 2015年10月13日
     */
    public static Date parseYyyyMmDdSplitHhMmSs(String dateStr) {
        return StringUtils.isEmpty(dateStr) ? null : DateTimeFormatUtils
                .parseYyyyMmDdSplitHhMmSsSplit(dateStr, true);
    }

    /**
     * 将Date转为Calendar
     * 
     * @param date
     * @return
     * @author zhangYao 568677
     * @date 2015年11月12日
     */
    public static Calendar date2Calendar(Date date) {
        if (null == date) {
            return null;
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            return calendar;
        }
    }

    /**
     * 将Calendar转为Date
     * 
     * @param date
     * @return
     * @author zhangYao 568677
     * @date 2015年11月12日
     */
    public static Date calendar2Date(Calendar date) {
        if (null == date) {
            return null;
        } else {
            return date.getTime();
        }
    }

    /**
     * 将Calendar转为Date
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年1月28日
     */
    public static String date2String(Date date) {
        if (null == date) {
            return "";
        } else {
            return new SimpleDateFormat(DATE_TIME).format(date);
        }
    }
    
    /**
     * 将YYYY-MM-DD HH:MM:SS
     * 小时是24小时制
     * @param date
     * @return
     * @author 879149
     * @date 2016年1月28日
     */
    public static Date string2DateH24(String date) {
        if (null == date) {
            return null;
        } else {
            try {
                return new SimpleDateFormat(DATE_TIME).parse(date);
            } catch (ParseException e) {
                logger.error("DateUtil dateFormat execute error--{}", e);
                return null;
            }
        }
    }
    
    /**
     * @Title 将YYYY-MM-DD HH:MM格式的时间转换成时间
     * @Description 将YYYY-MM-DD HH:MM格式的时间转换成时间
     * @param date:YYYY-MM-DD HH:MM格式的时间
     * @return Date:转换后的时间
     * @author 80002089
     * @Date 2016年11月24日
     */
    public static Date string2DateNotSecond(String date) throws ParseException{
        return StringUtil.isNilString(date)? null:new SimpleDateFormat(DATE_MINUTE).parse(date);
    }


    /**
     * 
     * @Description:string2YYYYMMDD
     * @param date
     * @return
     * @createUser:854186
     * @createTime:2016年11月25日下午2:46:56
     */
    public static Date String2DateYYYYMMDD(String date){
        try {
            return new SimpleDateFormat(DATE).parse(date);
        } catch (ParseException e) {
            logger.error("DateUtil dateFormat execute error=>{}", e.getMessage());
        }
        return null;
    }
    
    /**
     * 将Calendar转为Date
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年1月28日
     */
    public static Date dateFormat(Date date) {
        try {
            if (null == date) {
                return null;
            }
            return new SimpleDateFormat(DATE_TIME).parse(new SimpleDateFormat(DATE_TIME).format(date));
        } catch (Exception e) {
            logger.error("DateUtil dateFormat execute error", e);
        }
        return null;
    }
    
    /**
     * 替换日期，时分秒不变
     * 例如：
     *       sourceDate 为 2016-06-22 15:01:01, replaceDateStr 为 2016-06-01
     *       则返回 2016-06-01 15:01:01
     * @param sourceDate 原日期
     * @param replaceDateStr 需要替换的日期 格式必须为 YYYY/MM/DD
     * @return
     * @throws ParseException 
     */
    public static Date replaceDateBy(Date sourceDate, String replaceDateStr) throws ParseException{
        if (sourceDate == null || StringUtil.isNilString(replaceDateStr)){
            return sourceDate;
        }
        replaceDateStr = replaceDateStr.replace("/", "-");
        
        String sourceDateStr = new SimpleDateFormat(DATE_TIME).format(sourceDate);
        
        return new SimpleDateFormat(DATE_TIME).parse(replaceDateStr + sourceDateStr.substring(10));
    }
    
    /**
     * @Title 获取时间的年月日
     * @Description 获取时间的年月日:2016-06-22
     * @param sourceDate:时间
     * @return String:年月日
     * @Date 2016年11月11日
     */
    public static String getDateStr(Date sourceDate){
        if(null != sourceDate){
            return new SimpleDateFormat(DATE).format(sourceDate);
        }
        return null;
    }
    

    /**
     * 分钟时间相加
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年1月28日
     */
    public static Date addMinuteDate(Date date, int minute) {
        if (null != date) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MINUTE, minute);//
            return calendar.getTime();
        }
        return null;
    }
    
    /**
     * 时间相加
     * @param dateTime  需要进行相加的时间
     * @param dateTimeType
     * @param addValue
     * @return dateTime为空时，设置dateTime为当前时间
     * @author 80002031-2018年1月8日
     */
    public static Date addDateTime(Date dateTime,DateTimeType dateTimeType,int addValue){
        if (null == dateTime){
            dateTime = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateTime);
        calendar.add(dateTimeType.getType(), addValue);
        return calendar.getTime();
    }

    
    
    /**
     * 判断时间是否符合标准格式
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年3月10日
     */
    public static boolean isValidDate(String str) {
        boolean convertSuccess = true;
        try {
            if (StringUtils.isNotEmpty(str)) {
                DateTimeFormatUtils.parseYyyyMmDdSplitHhMmSsSplit(str, true);
            } else {
                convertSuccess = false;
            }
        } catch (Exception e) {
            convertSuccess = false;
            logger.error(ExceptionUtils.extractStackTrace(e));
        }
        return convertSuccess;
    }
    
    /**
     * 判断时间是否符合标准格式
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年3月10日
     */
    public static boolean isValidAppointDate(String str) {
        boolean convertSuccess = true;
        try {
            if (StringUtils.isNotEmpty(str)) {
                if(str.length()<=16){//yyyy-MM-dd HH:mm为16位,小于则补
                    str=str+":00";
                }
                DateTimeFormatUtils.parseYyyyMmDdSplitHhMmSsSplit(str, true);
            } else {
                convertSuccess = false;
            }
        } catch (Exception e) {
            convertSuccess = false;
            logger.error(ExceptionUtils.extractStackTrace(e));
        }
        return convertSuccess;
    }
    
    /**
     * 获取当前时间的值(精确到毫秒后三位) 格式为yyyyMMddHHmmssSSS 共有17位，用于生成顺丰订单号
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年5月12日
     */
    public static String getOrderNoTime() {
        return new SimpleDateFormat(DATE_TIME_FOR_ORDER_NO).format(new Date());
    }

    /**
     * 传过来的时间与当前时间做比较,如果在当前时间之前,就返回FALSE,反之,返回TRUE
     * 
     * @param date
     *            系统传过来的日期
     * @return boolean
     * @author 879149
     * @date 2016年5月23日
     */
    public static boolean compareDate(String date) {
        try {
            Date date1 = new SimpleDateFormat(DATE_TIME).parse(date);
            Date nowDate = new Date();
            if (date1.getTime() < nowDate.getTime()) {
                return false;
            }
        } catch (Exception e) {
            logger.error("DateUtil compareDate execute error", e);
            return false;
        }
        return true;
    }

    /**
     * 将String转为Date
     * @param date
     * @return
     * @author 879149
     * @date 2016年7月27日
     */
    public static Date stringToDate(String date) {
        try {
            if (StringUtils.isEmpty(date)) {
                return null;
            } else {
                if(date.length()<=16){//yyyy-MM-dd HH:mm为16位,小于则补,兼容预约时间
                    date=date+":00";
                }
                return DateTimeFormatUtils
                        .parseYyyyMmDdSplitHhMmSsSplit(date, true);
            }
        } catch (Exception e){
            logger.error("DateUtil stringToDate execute error", e);
            return null;
        }
    }

    /**
     * 当前时间加上小时时间
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年6月14日
     */
    public static Date addHourDate(Date date, int hour) {
        if (null != date) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.HOUR, hour);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 时间加上天数后的时间
     * 
     * @param date
     *            传入日期
     * @param day
     *            天数
     * @return
     * @author 80002088
     * @date 2016年6月20日
     */
    public static Date addDayDate(Date date, int day) {
        if (null != date) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.DATE, day);
            return calendar.getTime();
        }
        return null;
    }

    /**
     * 将String转为Date
     * 
     * @param date
     * @return
     * @author 879149
     * @date 2016年6月16日
     */
    public static Date String2Date(String date) {
        try {
            return DateTimeFormatUtils
                    .parseYyyyMmDdSplitHhMmSsSplit(date, true);
        } catch (Exception e) {
            logger.error("DateUtil String2Date execute error {}--{}", date, e);
        }
        return null;
    }
    /**
     * 将String转为Date
     * @param date
     * @return
     * @author 879149
     * @date 2016年6月20日
     */
    public static Date StringSdf2Date(String date) {
        try{
            return new SimpleDateFormat(DATE_TIME_NUMBER_MM).parse(date);
        }catch(Exception e){
            logger.error("DateUtil StringSdf2Date execute error {}--{}",date,e);
        }
        return null;
    }
    
    /**
     * @Description 将String转为Date
     * @Param date 时间String
     * @Return Date 
     */
    public static Date String2YyMmDd(String date) {
        try{
            return DateTimeFormatUtils.parseYyyyMmDdSplit(date);
        }catch(Exception e){
            logger.error("DateUtil String2Date execute error {}--{}",date,e);
        }
        return null;
    }
    
    /**
     * @Description 将Date格式设为yyyy-MM-dd
     * @Param date 转化前日期
     * @Return Date 转化后日期
     */
    public static Date dateFormat2YyMmDd(Date date) {
        try {
            if (null == date) {
                return null;
            }
            return new SimpleDateFormat(DATE).parse(new SimpleDateFormat(DATE).format(date));
        } catch (Exception e) {
            logger.error("DateUtil dateFormat execute error", e);
        }
        return null;
    }
    
    
    /**
     * 
     * @Description:比较2个字符串日期时间，日期格式为yyyymmdd
     * 当d1>d2,返回1
     * 当d1<d2,返回-1
     * 当d1=d2,返回0
     * @param date1
     * @param date2
     * @return
     * @createUser:854186
     * @createTime:2016年7月21日上午10:42:31
     */
    public static int compare(String date1,String date2){
        Date d1=String2YyMmDd(date1);
        Date d2=String2YyMmDd(date2);
        if(d1.getTime()>d2.getTime()){
            return 1;
        }
        if(d1.getTime()<d2.getTime()){
            return -1;
        }else{
            return 0;
        }
    }
    /**
     * 
     * @Description:比较2个日期大小，当d1>d2返回-1，d1<d2返回1
     * @param d1
     * @param d2
     * @return
     * @createUser:854186
     * @createTime:2016年7月28日下午7:48:30
     */
    public static int compare(Date d1,Date d2){
        if(d1.getTime()>d2.getTime()){
            return 1;
        }else if(d1.getTime()<d2.getTime()){
            return -1;
        }else{
            return 0;
        }
    }
    /**
     * 
     * @Description:获得2个日期相差的小时数
     * @param d1
     * @param d2
     * @return
     * @createUser:854186
     * @createTime:2016年7月21日上午10:42:54
     */
        public static int getHours(Date d1,Date d2){
            long diff=d1.getTime()-d2.getTime();//获得相差的毫秒数
            return (int) (diff/1000/3600);
        }
        
        
        /**
         * 
         * @Description:Date格式转xmlCalendar
         * @param date
         * @return
         * @createUser:854186
         * @createTime:2016年7月21日上午10:43:27
         */
        public static XMLGregorianCalendar convertToXMLGregorianCalendar(Date date) {

            GregorianCalendar cal = new GregorianCalendar();
            cal.setTime(date);
            XMLGregorianCalendar gc = null;
            try {
                gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
            } catch (Exception e) {
                //打印日志
                logger.error("DateUtil XMLGregorianCalendar() is error-{}", ExceptionUtils.extractStackTrace(e));
            }
            return gc;
        }
        /**
         * 
         * @Description:XML转DATE
         * @param cal
         * @return
         * @throws OmsException
         * @createUser:854186
         * @createTime:2016年7月21日上午10:43:41
         */
        public static Date convertToDate(XMLGregorianCalendar cal){
            GregorianCalendar ca = cal.toGregorianCalendar();
            return ca.getTime();
        }
        
        /**
         * 传过来的时间去掉时分秒与当前时间做比较,如果在当前时间之前,就返回FALSE,反之,返回TRUE
         * 
         * @param date
         *            系统传过来的日期
         * @return boolean
         * @author 879149
         * @date 2016年6月8日
         */
        public static boolean compareNowDate(String date) {
            try {
                Date date1 =DateTimeFormatUtils.parseYyyyMmDdSplit(date);
                Date nowDate = new Date();
                if (date1.getTime() > nowDate.getTime()) {
                    return true;
                }
            } catch (Exception e) {
                logger.error("DateUtil compareDate execute error", e);
                return false;
            }
            return false;
        }
    
    /**
     * 获取指定一天的起始时间 <br>
     * 如：2016-08-25 00:00:00
     * 
     * @param date
     *            时间
     * @return 起始时间
     * @author 866321
     * @date 2016-08-25
     */
    public static Date getOneDayStart(Date date) {
        Date result = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            result = sdf.parse(sdf.format(date));
        } catch (ParseException e) {
            throw new OmsRuntimeException(e);
        }
        return result;
    }

    /**
     * 获取指定一天的结束时间 <br>
     * 如：2016-08-25 00:00:00
     * 
     * @param date
     *            时间
     * @return 结束时间
     * @author 866321
     * @date 2016-08-25
     */
    public static Date getOneDayEnd(Date date) {
        Date result = null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            Date temp = sdf.parse(sdf.format(date));
            result = new Date(temp.getTime() + CommonConstant.MILLISECOND_ONE_DAY - 1);
        } catch (ParseException e) {
            throw new OmsRuntimeException(e);
        }
        return result;
    }
    
    /**
     * 判断指定日期是否在今天内
     * 
     * @param date
     *            指定日期
     * @return 是否在今天内
     * @author 866321
     * @date 2016-08-25
     */
    public static boolean isInToday(Date date) {
        long syn = date.getTime();
        Date today = new Date();
        long start = DateUtil.getOneDayStart(today).getTime();
        long end = DateUtil.getOneDayEnd(today).getTime();
        if (syn >= start && syn <= end) {
            return true;
        }
        return false;
    }
    
    /**
     * 格式化日期
     * 
     * @param date
     *            日期
     * @param dateFormat
     *            格式化样式
     * @return 日期字符串
     */
    public static String formatDate(Date date, String dateFormat) {
        if (null != date && StringUtils.isNotBlank(dateFormat)) {
            return new SimpleDateFormat(dateFormat).format(date);
        }
        return null;
    }

    /**
     * 解析日期字符串
     * 
     * @param source
     *            日期字符串
     * @param dateFormat
     *            日期格式
     * @return 日期
     */
    public static Date parse(String source, String dateFormat) {
        try {
            if (StringUtils.isNotEmpty(source)) {
                return new SimpleDateFormat(dateFormat).parse(source);
            }
            return null;
        } catch (ParseException e) {
            throw new OmsRuntimeException(e);
        }
    }
    
    /**
     * @Title 判断时间是否在有效期内
     * @Description 判断时间是否在有效期内
     *                 1、time不能为空
     *                 2、时间只比较日期，开始时间默认0点，结束时间默认23点59分59秒；
     * @param time：是否在有效的时间
     * @param timeStart：开始时间
     * @param timeEnd：失效期，可以为空，为空在无失效期
     * @return boolean：true：在有效期内，false：不在有效期内
     * @author 80002089
     * @Date 2016年11月11日
     */
    public static boolean judgeValid(Date time,Date timeStart,Date timeEnd){
        if(null != time && null != timeStart){
            timeStart = parseYyyyMmDdSplitHhMmSs(getDateStr(timeStart)+" 00:00:00" );
            if(0 >= timeStart.compareTo(time)){
                if(null != timeEnd){
                    timeEnd = parseYyyyMmDdSplitHhMmSs(getDateStr(timeEnd)+" 23:59:59" );
                    if(0 >= time.compareTo(timeEnd)){
                        return true;
                    }
                }else{
                    return true;
                }
            }
        }
        return false;
    }
    
    /**
     * @Title 判断时间是在开始时间，结束时间 区间内
     * @Description 判断时间是在开始时间，结束时间 区间内
     * @param time：比较时间
     * @param timeStart：开始时间
     * @param timeEnd：结束时间
     * @return Boolean：true：在区间内，false：不在区间内
     * @author 80002089
     * @Date 2016年11月23日
     */
    public static boolean judgeTimeInterval(Date date,Date startDate,Date endDate){
        if(null != date && null != startDate && 0 >= startDate.compareTo(date)){
            if(null != endDate){
                if(0 >= date.compareTo(endDate)){
                    return true;
                }
            }else{
                return true;
            }
        }
        return false;
    }
    
    
    /**
     * @Title 判断时间是在开始时间，结束时间 区间内
     * @Description 判断时间是在开始时间，结束时间 区间内
     *                 开始时间格式 --时分秒 00:00:00
     * @param time：比较时间
     * @param timeStart：开始时间--时分秒 00:00:00
     * @param timeEnd：结束时间--时分秒 00:00:00
     * @return Boolean：true：在区间内，false：不在区间内
     * @author 80002089
     * @Date 2016年11月23日
     */
    public static boolean judgeTimeInterval(Date time,String startDate,String endDate){
        if(null != time){
            Date start = parseYyyyMmDdSplitHhMmSs(getDateStr(time) + " " + startDate);
            Date end = parseYyyyMmDdSplitHhMmSs(getDateStr(time)+ " " + endDate);
            return judgeTimeInterval(time, start, end);
        }
        return false;
    }
    
    /** 
     * 将Date类转换为XMLGregorianCalendar 
     * @param date 
     * @return  
     */  
    public static XMLGregorianCalendar dateToXmlDate(Date date){  
            if (null != date){
                Calendar cal = Calendar.getInstance();  
                cal.setTime(date);  
                DatatypeFactory dtf = null;  
                 try {  
                    dtf = DatatypeFactory.newInstance();  
                } catch (DatatypeConfigurationException e) {  
                    logger.error(" DatatypeFactory newInstance execute error ! ,Exception : {}" ,ExceptionUtils.extractStackTrace(e));
                }  
                 if (null != dtf){
                     XMLGregorianCalendar dateType = dtf.newXMLGregorianCalendar();  
                     dateType.setYear(cal.get(Calendar.YEAR));  
                     //由于Calendar.MONTH取值范围为0~11,需要加1  
                     dateType.setMonth(cal.get(Calendar.MONTH)+1);  
                     dateType.setDay(cal.get(Calendar.DAY_OF_MONTH));  
                     dateType.setHour(cal.get(Calendar.HOUR_OF_DAY));  
                     dateType.setMinute(cal.get(Calendar.MINUTE));  
                     dateType.setSecond(cal.get(Calendar.SECOND));  
                     return dateType; 
                 } 
            } 
            return null;
        }   
  
    /** 
     * 将XMLGregorianCalendar转换为Date 
     * @param cal 
     * @return  
     */  
    public static Date xmlDate2Date(XMLGregorianCalendar cal){  
        if (null != cal){
            return cal.toGregorianCalendar().getTime();
        }else{
            return null;
        }
    }  
    
    public enum DateTimeType{
        YEAR(1,"年"),
        MONTH(2,"月"),
        DATE(5,"日"),
        HOUR(10,"小时"),
        MINUTE(12,"分钟"),
        SECOND(13,"秒");
        
        private Integer type;   //类型
        private String desc;      //描述  
        
        private DateTimeType(Integer type, String desc) {
            this.type = type;
            this.desc = desc;
        }
        
        public Integer getType() {
            return type;
        }
        public String getDesc() {
            return desc;
        }
        
    }
    
}

    
